package com.movie.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.movie.entity.User;
import com.movie.entity.vo.ResultVo;
import com.movie.utils.JsonUtils;
import com.movie.utils.JwtUtils;
import com.movie.utils.RsaUtils;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.security.PublicKey;

@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {
    @Value("${URI.white}")
    private String URI_WHITE;  //白名单

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //放行资源
        URI uri = request.getURI();
        String[] whites = URI_WHITE.split(",");
        for (String white : whites) {
            if (uri.getPath().equals(white)){
                return chain.filter(exchange);
            }

        }


        //判断请求头中是否有token
        String token = request.getHeaders().getFirst("token");
        if (token == null) {
            //不能放行,响应客户端
            return response(response, new ResultVo(false, "请登录","invalid token"));
        }
        PublicKey publicKey = null;
        try {
            //获取公钥
            publicKey = RsaUtils.getPublicKey(String.valueOf(ResourceUtils.getFile("classpath:rsa.pub")));
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            //校验令牌
            User userInfo = (User) JwtUtils.getInfoFromToken(token, publicKey, User.class);

            //传递用户信息（请求头）
            ServerHttpRequest newRequest = request.mutate().header("userInfo", JsonUtils.toString(userInfo)).build();
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
            //放行
            return chain.filter(newExchange);


        } catch (MalformedJwtException e) {
            e.printStackTrace();
            return response(response, new ResultVo(false, "非法令牌","invalid token"));
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            return response(response, new ResultVo(false, "令牌过期","invalid token"));
        } catch (Exception e) {
            e.printStackTrace();
            return response(response, new ResultVo(false, "其他异常","invalid token"));
        }

    }

    @Override
    public int getOrder() {
        return 0;
    }

    private Mono<Void> response(ServerHttpResponse response, ResultVo res) {
        //不能放行，直接返回，返回json信息
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");

        ObjectMapper objectMapper = new ObjectMapper();
        String jsonStr = null;
        try {
            jsonStr = objectMapper.writeValueAsString(res);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }


        DataBuffer dataBuffer = response.bufferFactory().wrap(jsonStr.getBytes());

        return response.writeWith(Flux.just(dataBuffer));//响应json数据
    }
}
